package com.platform.service.impl;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.google.common.collect.Maps;
import com.platform.annotation.Authentication;
import com.platform.config.LocalAttachPath;
import com.platform.minio.Assert;
import com.platform.minio.Minio;
import com.platform.minio.exception.FileServiceException;
import com.platform.service.IMinioFileService;

import cn.hutool.core.io.FastByteArrayOutputStream;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;


@Service
public class MinioFileServiceImpl implements IMinioFileService{

	@Resource
	private Minio minioRepository;
	
	private static Map<String, String> contentTypeMap;
	
	private final static String DEFAULT_CONTENT_TYPE = "application/octet-stream";
	
	static {
		contentTypeMap = Maps.newHashMap();
		contentTypeMap.put("doc", "application/msword");
		contentTypeMap.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
		contentTypeMap.put("pdf", "application/pdf");
		contentTypeMap.put("xls", "application/vnd.ms-excel");
		contentTypeMap.put("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
		contentTypeMap.put("ppt", "application/vnd.ms-powerpoint");
		contentTypeMap.put("pptx", "pplication/vnd.openxmlformats-officedocument.presentationml.presentation");
		contentTypeMap.put("rar", "application/x-rar-compressed");
		contentTypeMap.put("gif", "image/gif");
		contentTypeMap.put("jpeg","image/jpeg");
		contentTypeMap.put("jpg", "image/jpeg");
		contentTypeMap.put("png", "image/png");
		contentTypeMap.put("txt", "text/plain");
		contentTypeMap.put("zip", "application/x-zip-compressed");
	}
	
	/**
	 * @Title: upload   
	 * @Description: 文件上传
	 * @author: <a href="mailto:15909910367@163.com">吴先生</a>
	 * @param bucket 存储桶
	 * @param file	文件对象MultipartFile
	 * @return
	 * @throws Exception      
	 * String
	 */
	@Override
	@Authentication
	public String upload(String bucket, MultipartFile file) throws Exception {
		Assert.notBlank(bucket, "bucket不能为空");
		long size = file.getSize();
		if(size <= 0)
			throw new FileServiceException("上传的文件不能为空");
		if(!minioRepository.checkBucket(bucket))
			minioRepository.createBucket(bucket);
//			throw new FileServiceException("该bucket："+bucket+" 不存在");
		// 组成新的文件名
		String fileName = IdUtil.objectId() + "." + getExt(file.getOriginalFilename());
		minioRepository.put(bucket, fileName, file.getInputStream(), size, file.getContentType());
		return fileName;
	}

	/**
	 * @Title: download   
	 * @Description: 文件下载  
	 * @author: <a href="mailto:15909910367@163.com">吴先生</a>
	 * @param bucket	存储桶
	 * @param fileId	
	 * @param response
	 * @throws Exception      
	 * void
	 */
	@Override
	@Authentication
	public void download(String bucket, String fileId, HttpServletResponse response) throws Exception {
		Assert.notBlank(bucket, "bucket不能为空");
		Assert.notBlank(fileId, "文件Id不能为空.");
		InputStream in = minioRepository.get(bucket, fileId);
		// 设置响应头
		String contentType = contentTypeMap.get(getExt(fileId));
        response.setContentType(StrUtil.isNotBlank(contentType) ? contentType : DEFAULT_CONTENT_TYPE);
        String fileName = encodeFileName(fileId);
        //下载文件能正常显示中文
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        FastByteArrayOutputStream buffer = IoUtil.read(in);
		IoUtil.write(response.getOutputStream(), false, buffer.toByteArray());
	}
	
	@Override
	@Authentication
	public String downSaveLocal(String bucket, String fileId, HttpServletResponse response) throws Exception {
		String absSaveFilePath = LocalAttachPath.get("file.root")+File.separator+bucket+File.separator+fileId;
		if(!FileUtil.exist(absSaveFilePath)) {
			FileUtil.mkParentDirs(absSaveFilePath);
		}
		Assert.notBlank(bucket, "bucket不能为空");
		Assert.notBlank(fileId, "文件Id不能为空.");
		InputStream in = minioRepository.get(bucket, fileId);
        BufferedOutputStream outBuffer = new BufferedOutputStream(new FileOutputStream(new File(absSaveFilePath)));
        int index;
		byte[] bytes = new byte[1024];
		while ((index = in.read(bytes)) != -1) {
			outBuffer.write(bytes, 0, index);
			outBuffer.flush();
		}
		outBuffer.close();
		in.close();
		return absSaveFilePath;
	}
	
	/**
	 * @Title: preview   
	 * @Description: 生成文件预览地址  
	 * @author: <a href="mailto:15909910367@163.com">吴先生</a>
	 * @param bucket	存储桶
	 * @param fileName	文件名称
	 * @return      
	 * String
	 */
	@Override
	@Authentication
	public String preview(String bucket,String fileName) {
		Assert.notBlank(bucket, "bucket不能为空");
		Assert.notBlank(fileName, "文件名称不能为空.");
		return minioRepository.preview(bucket, fileName);
	}
	
	/**
	 * @Title: delete   
	 * @Description: 文件删除
	 * @author: <a href="mailto:15909910367@163.com">吴先生</a>
	 * @param bucket	存储桶
	 * @param fileName	文件名称
	 * @throws Exception      
	 * void
	 */
	@Override
	@Authentication
	public void delete(String bucket, String fileName) throws Exception {
		Assert.notBlank(bucket, "bucket不能为空");
		Assert.notBlank(fileName, "文件名不能为空.");
		minioRepository.delete(bucket, fileName);
	}

	/**
	 * 对中文名称进行编码
	 * @param filename 文件名称
	 * @return
	 */
	@Authentication
	private String encodeFileName(String filename){
		return URLUtil.encode(filename);
	}
	
	/**
	 * 得到文件后缀名
	 * @param filename 文件完整名称
	 * @return 文件后缀
	 */
	@Authentication
	private String getExt(String filename){
		String extName = StrUtil.subAfter(filename, '.', true);
		return StrUtil.isNotBlank(extName) ? extName : ""; 
	}
}
